package com.blate.dogxiao.adapter;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ViewDataBinding;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

/**
 * 带有数据的RecycleView Adapter.
 * 其他特性同{@link SimpleRecyclerViewAdapter}
 *
 * @author Az
 * on 2020/10/20
 */
public abstract class SimpleDataRecyclerViewAdapter<D, VB extends ViewDataBinding>
        extends RecyclerView.Adapter<SimpleDataRecyclerViewAdapter.SimpleDataHolder<D, VB>> {

    protected MonitorViewCollector<VB> mMonitorViewCollector;
    protected OnItemChildClickListener<VB, D> mOnItemChildClickListener;

    protected LongClickViewCollector<VB> mLongClickViewCollector;
    protected OnItemChildLongClickListener<VB, D> mOnItemChildLongClickListener;

    protected ObservableArrayList<D> mDataList = new ObservableArrayList<>();

    /**
     * 子类重写这个方法,提供ViewDataBinding
     *
     * @param inflater inflater
     * @param parent   parent
     * @param viewType viewType
     * @return VB
     */
    protected abstract VB onCreateBinding(LayoutInflater inflater, ViewGroup parent, int viewType);

    public abstract void onBindViewHolder(@NonNull SimpleDataHolder<D, VB> holder, D data);

    public void putData(boolean refresh, List<D> data) {
        if (refresh) {
            mDataList.clear();
        }
        if (data != null) {
            mDataList.addAll(data);
        }
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public SimpleDataHolder<D, VB> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        VB binding = onCreateBinding(LayoutInflater.from(parent.getContext()), parent, viewType);
        SimpleDataHolder<D, VB> holder = new SimpleDataHolder<>(binding);
        holder.setOnItemChildClickListener(mOnItemChildClickListener);
        holder.setOnItemChildLongClickListener(mOnItemChildLongClickListener);
        if (mMonitorViewCollector != null) {
            mMonitorViewCollector.collectorMonitorView(holder, binding);
        }
        if (mLongClickViewCollector != null) {
            mLongClickViewCollector.collectorView(holder, binding);
        }
        return holder;
    }

    @Override
    public int getItemCount() {
        return mDataList.size();
    }

    @Override
    public void onBindViewHolder(@NonNull SimpleDataHolder<D, VB> holder, int position) {
        D data = mDataList.get(position);
        holder.bindData(data);
        onBindViewHolder(holder, data);
    }

    public List<D> getDataList() {
        return mDataList;
    }

    /**
     * 设置条目点击监听
     *
     * @param collector 收集器,收集需要监听的视图
     * @param listener  监听器,被收集视图的响应事件触发后会回调到该方法
     */
    public void setItemChildClickListener(MonitorViewCollector<VB> collector, OnItemChildClickListener<VB, D> listener) {
        this.mMonitorViewCollector = collector;
        this.mOnItemChildClickListener = listener;
    }

    public void setItemLongClickListener(LongClickViewCollector<VB> collector, OnItemChildLongClickListener<VB, D> listener) {
        this.mLongClickViewCollector = collector;
        this.mOnItemChildLongClickListener = listener;
    }

    /**
     * 条目视图监听器
     * 一个View的点击事件能被监听前提:
     * 调用{@link #setItemChildClickListener(MonitorViewCollector, OnItemChildClickListener)}时
     * 在MonitorViewCollector中调用了{@link MonitorViewCollector#collectorMonitorView(ItemViewMonitor, Object)}中
     * 收集了视图.而且在{@link ItemViewMonitor#monitorView(View)}中监视了View的点击事件,在点击事件触发时回
     * 调了此方法
     *
     * @param <D> 数据类型
     */
    public interface OnItemChildClickListener<VB, D> {

        /**
         * 点击事件回调
         *
         * @param view view被点击了
         * @param data 点击条目绑定的数据
         */
        void onItemChildClick(VB binding, View view, D data);

    }

    /**
     * 这个接口用收集需要监视的View
     * View应该存在于{@link SimpleDataHolder#getBinding()} ()}中
     *
     * @param <VB> 从 VB 中收集监视视图
     */
    public interface MonitorViewCollector<VB> {

        /**
         * 收集需要监视的视图
         *
         * @param itemViewMonitor view监视器
         * @param binding         binding
         */
        void collectorMonitorView(ItemViewMonitor itemViewMonitor, VB binding);

    }

    /**
     * 长按事件响应view收集器
     *
     * @param <VB>
     */
    public interface LongClickViewCollector<VB> {

        void collectorView(ItemViewLongClickMonitor itemViewLongClickMonitor, VB binding);

    }

    public interface OnItemChildLongClickListener<VB, D> {

        boolean onItemChildClick(VB binding, View view, D data);

    }

    public interface ItemViewLongClickMonitor {

        void monitorLongClickView(View view);

    }

    /**
     * View监视器
     */
    public interface ItemViewMonitor {

        /**
         * 调用这个方法监视一个视图.
         * 根据实现类不同可以监听View的不同的事件(ex : 点击,长按...)
         *
         * @param view 被监视的View
         */
        void monitorView(View view);

    }

    public static class SimpleDataHolder<D, VB extends ViewDataBinding>
            extends RecyclerView.ViewHolder
            implements ItemViewMonitor, View.OnClickListener,
            ItemViewLongClickMonitor, View.OnLongClickListener {

        private OnItemChildClickListener<VB, D> mOnItemChildClickListener;

        private OnItemChildLongClickListener<VB, D> mOnItemChildLongClickListener;

        private D mData;
        private VB mViewDataBinding;

        public SimpleDataHolder(@NonNull VB binding) {
            super(binding.getRoot());
            this.mViewDataBinding = binding;
        }

        protected void setOnItemChildClickListener(OnItemChildClickListener<VB, D> listener) {
            this.mOnItemChildClickListener = listener;
        }

        protected void setOnItemChildLongClickListener(OnItemChildLongClickListener<VB, D> listener) {
            this.mOnItemChildLongClickListener = listener;
        }

        public void bindData(D data) {
            this.mData = data;
        }

        public VB getBinding() {
            return mViewDataBinding;
        }

        @Override
        public void onClick(View v) {
            if (mOnItemChildClickListener != null) {
                mOnItemChildClickListener.onItemChildClick(mViewDataBinding, v, mData);
            }
        }

        /**
         * 监视了View的点击事件,在这里事件由{@link #mOnItemChildClickListener}分发
         *
         * @param view 被监视的View
         */
        @Override
        public void monitorView(View view) {
            view.setOnClickListener(this);
        }

        @Override
        public void monitorLongClickView(View view) {
            view.setOnLongClickListener(this);
        }

        @Override
        public boolean onLongClick(View v) {
            if (mOnItemChildLongClickListener != null) {
                return mOnItemChildLongClickListener.onItemChildClick(mViewDataBinding, v, mData);
            } else {
                return false;
            }
        }
    }


}
